﻿#pragma once

#include <learn/dll_ext.h>
#include <learn/math/matrix_solver.h>

namespace xi
{

namespace math
{

class EXT_SYMBOL Integrator
{
  public:
    /**
     * @brief 构造函数
     *
     * @param[in] N 节点数
     */
    explicit Integrator(std::size_t N);

    /**
     * @brief 获取节点数
     *
     * @return std::size_t
     */
    std::size_t node_num() const;

    /**
     * @brief 积分接口
     *
     * @param[in] f
     * @param[in] a
     * @param[in] b
     * @return double
     */
    virtual double operator()(double (*f)(double), double a, double b) = 0;

  protected:
    std::size_t m_N; // 节点数
};

class EXT_SYMBOL Integrator_Trapezoidal : public Integrator
{
  public:
    /**
     * @brief 节点数
     *
     * @param[in] N
     */
    explicit Integrator_Trapezoidal(std::size_t N);

    /**
     * @brief 积分接口
     *
     * @param[in] f
     * @param[in] a
     * @param[in] b
     * @return double
     */
    double operator()(double (*f)(double), double a, double b) override;
};

class EXT_SYMBOL Integrator_Simpson : public Integrator
{
  public:
    /**
     * @brief 节点数，必须为奇数
     *
     * @param[in] N
     */
    explicit Integrator_Simpson(std::size_t N);

    /**
     * @brief 积分接口
     *
     * @param[in] f
     * @param[in] a
     * @param[in] b
     * @return double
     */
    double operator()(double (*f)(double), double a, double b) override;
};

class EXT_SYMBOL Integrator_Gauss : public Integrator
{
  public:
    /**
     * @brief 节点数
     *
     * @param[in] N
     */
    explicit Integrator_Gauss(std::size_t N);

    /**
     * @brief 积分接口
     *
     * @param[in] f
     * @param[in] a
     * @param[in] b
     * @return double
     */
    double operator()(double (*f)(double), double a, double b) override;

    std::vector<double> weights; // 积分权
    std::vector<double> nodes;   // 积分节点
};

} // namespace math

} // namespace xi
